//-----------------------------------------------------------------------
// <copyright file="Create.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Mark Phillips</author>
// <email>v-mphill@microsoft.com</email>
// <date>2004-05-24</date>
// <summary>Creates a Cluster Resource Property.</summary>
//-----------------------------------------------------------------------
#if CLUSTER
namespace Microsoft.Sdc.Tasks.Cluster.Resource.Property
{
    #region Using directives

    using System;
    using System.Globalization;
    using System.Reflection;
    using System.Collections;
    using System.Runtime.InteropServices;
    using Microsoft.Cluster.Interop;
    using Microsoft.Build.Framework;

    #endregion

    /// <summary>
    /// Creates a Cluster Resource Property.
    /// </summary>          
    /// <remarks>
    /// <code><![CDATA[
    /// <Cluster.Resource.Property.Create
    ///             Resource="resource"
    ///             Property="property"
    ///             PropertyValue="propertyValue"
    ///             Cluster="cluster"
    ///             Force="force" >
    /// </Cluster.Resource.Property.Create>
    /// ]]></code>
    /// <para>where:</para>
    /// <para><i>resource (Required)</i></para>
    /// <para>TODO</para>
    /// <para><i>property (Required)</i></para>
    /// <para>TODO</para>
    /// <para><i>propertyValue</i></para>
    /// <para></para>
    /// <para><i>cluster</i></para>
    /// <para></para>
    /// <para><i>force</i></para>
    /// <para></para>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <Target Name="Test" >
    ///         <Cluster.Resource.Property.Create
    ///             Resource="TODO"
    ///             Property="TODO"
    ///             PropertyValue="TODO"
    ///         </Cluster.Resource.Property.Create> 
    ///     </Target>
    /// </Project>
    /// ]]></code>    
    /// </example>
    public class Create : TaskBase
    {
        private string clusterName = String.Empty;
        private string resourceName = String.Empty;
        private string propertyName = String.Empty;
        private string propertyValue = String.Empty;
        private Microsoft.Cluster.Interop.Cluster cluster = null;
        private bool force = false;

        /// <summary>
        /// Initializes a new instance of the Cluster.Create class.
        /// </summary>
        public Create()
        {
        }

        /// <summary>
        /// The name of the cluster
        /// </summary>
        /// <value>Defaults to String.Empty</value>
        public string Cluster
        {
            get
            {
                return (this.clusterName == null ? String.Empty : this.clusterName);
            }

            set
            {
                this.clusterName = value;
            }
        }

        /// <summary>
        /// The name of the Cluster resource
        /// </summary>
        /// <value>Defaults to String.Empty</value>
        [Required]
        public string Resource
        {
            get
            {
                return (this.resourceName == null ? String.Empty : this.resourceName);
            }

            set
            {
                this.resourceName = value;
            }
        }

        /// <summary>
        /// The name of the cluster prooperty to set.
        /// </summary>
        /// <value>Defaults to String.Empty</value>
        [Required]
        public string Property
        {
            get
            {
                return (this.propertyName == null ? String.Empty : this.propertyName);
            }

            set
            {
                this.propertyName = value;
            }
        }

        /// <summary>
        /// The value to set Property with.
        /// </summary>
        /// <value>Defaults to String.Empty</value>
        [Required]
        public string PropertyValue
        {
            get
            {
                return (this.propertyValue == null ? String.Empty : this.propertyValue);
            }

            set
            {
                this.propertyValue = value;
            }
        }

        /// <summary>
        /// True to force overwriting of the property value
        /// </summary>
        /// <value>Defaults to FALSE.</value>
        public bool Force
        {
            get
            {
                return this.force;
            }

            set
            {
                this.force = value;
            }
        }

        /// <summary>
        /// Performs the action of this task.
        /// </summary>
        protected override void InternalExecute()
        {
            if (this.resourceName == null || this.resourceName.Length == 0)
            {
                throw new TaskException("ClusterServer.InvalidResource");
            }

            if (this.propertyName == null || this.propertyName.Length == 0)
            {
                throw new TaskException("ClusterServer.InvalidPropertyName");
            }

            if (this.propertyValue == null || this.propertyValue.Length == 0)
            {
                throw new TaskException("ClusterServer.InvalidPropertyValue");
            }

            try
            {
                this.cluster = new Microsoft.Cluster.Interop.Cluster();
                if (this.clusterName == null || this.clusterName.Length == 0)
                {
                    this.cluster.Open("");
                }
                else
                {
                    this.cluster.Open(this.clusterName);
                }
            }
            catch
            {
                throw new TaskException("ClusterServer.FailConnect", ((this.clusterName == null || this.clusterName.Length == 0) ? "localhost" : this.clusterName));
            }

            Console.WriteLine(String.Format(CultureInfo.InvariantCulture, "Connected to cluster {0}.", this.clusterName));

            Microsoft.Cluster.Interop.ClusResources resources = this.cluster.Resources;
            Microsoft.Cluster.Interop.ClusResource resource = resources[this.resourceName];

            if (resource == null)
            {
                throw new TaskException("ClusterServer.ResourceDoesNotExist", this.resourceName);
            }

            Microsoft.Cluster.Interop.ClusProperties properties = resource.PrivateProperties;
            Microsoft.Cluster.Interop.ClusProperty property = null;

            if (properties.Count > 0)
            {
                IEnumerator enumerator = properties.GetEnumerator();

                while (enumerator.MoveNext())
                {
                    Console.WriteLine(String.Format(CultureInfo.InvariantCulture, "Property: {0}.", ((Microsoft.Cluster.Interop.ClusProperty)enumerator.Current).Name));

                    if (((Microsoft.Cluster.Interop.ClusProperty) enumerator.Current).Name == this.propertyName)
                    {
                        property = (Microsoft.Cluster.Interop.ClusProperty) enumerator.Current;
                    }

                    if (((Microsoft.Cluster.Interop.ClusProperty) enumerator.Current).Name == "Security")
                    {
                        Microsoft.Cluster.Interop.ClusProperty tempProp = (Microsoft.Cluster.Interop.ClusProperty) enumerator.Current;
                        if (tempProp.ValueCount > 0)
                        {
                            Console.WriteLine("Security property contains some values.");
                            IEnumerator secEnum = tempProp.Values.GetEnumerator();
                            while (secEnum.MoveNext())
                            {
                                Console.WriteLine(String.Format(CultureInfo.InvariantCulture, "Security Property value: {0}.", ((Microsoft.Cluster.Interop.ClusPropertyValue) secEnum.Current).Value.ToString()));
                            }
                        }
                    }
                }
            }

            if (property != null && this.propertyValue != null && this.propertyValue.Length == 0 && this.force == true)
            {
                // The property already exists but force is true so lets change the value.
                Console.WriteLine("The property exists.  Changing it's value.");
                property.Value = this.propertyValue;
            }
            else if (property != null && this.propertyValue != null && this.propertyValue.Length == 0 && this.force == false)
            {
                // The property already exists but force is false so lets throw an error.
                Console.WriteLine("The property exists.  Not changing it's value.");
                throw new TaskException("ClusterServer.ForceNotSet");
            }
            else
            {
                try
                {
                    Console.WriteLine("The property does not exist.  Creating a new property.");
                    property = properties.CreateItem(this.propertyName, this.propertyValue);
                }
                catch (Exception ex)
                {
                    throw new TaskException("ClusterServer.CreateProperty", new string[] { this.propertyName, this.resourceName, ex.Message });
                }
            }

            object status = null;
            properties.SaveChanges(out status);

            Console.WriteLine(String.Format(CultureInfo.InvariantCulture, "Property {0} has been created.", this.propertyName));
        }
    }
}
#endif